package com.lsh.oms.core.proxy.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.atp.api.model.base.ExceptionStatus;
import com.lsh.base.common.exception.BusinessException;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.proxy.model.strategy.StraAttrResponse;
import com.lsh.oms.core.proxy.model.strategy.StrategyInfo;
import com.lsh.oms.core.proxy.model.strategy.StrategyRequest;
import com.lsh.oms.core.proxy.model.strategy.StrategySupplierRequest;
import com.lsh.oms.core.utils.http.HttpClientTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Project Name: StrategyProxy
 * 北京链商电子商务有限公司
 *
 * @author wangliutao
 * Date: 18/12/29
 * Package Name: com.lsh.atp.core.proxy
 * Description:
 */
@Slf4j
@Component
public class StrategyProxy implements InitializingBean {
    private static final String QUERY_STRATEGY_INFO_URL = "/strategy/get";
    private static final String QUERY_STRATEGY_ATTR_INFO_URL = "/strategy/attr/getAttrInfo";
    private static final String SUPPLIER_CONFIG_URL = "/strategy/supplier/add";
    private static final String STRATEGY_AUTH_URL = "/auth";
    private static final String username = "admin";
    private static final String password = "admin";
    private static String strategyToken = null;
    private AtomicLong authVersion = new AtomicLong(0L);

    private List<String> tokenErrorCodes;

    @Value("${strategy.server.host}")
    private String strategyHost;

    @Override
    public void afterPropertiesSet() throws BusinessException {
        tokenErrorCodes = new ArrayList<>();
        tokenErrorCodes.add("1002001");
        tokenErrorCodes.add("1002002");

        this.obtainStraAuth();
    }


    /**
     * 请求策略服务，获取策略信息
     *
     * @param request
     * @return
     */
    public List<StrategyInfo> queryStraInfo(StrategyRequest request) {
        List<StrategyInfo> strategyInfos = Collections.emptyList();
        String uri = this.strategyHost + QUERY_STRATEGY_INFO_URL;
        String content = JSON.toJSONString(request);
        try {
            log.info("[POST][strategy][URI={}] request: {}", uri, content);
            String respStr = HttpClientTemplate.doPostBody(uri, content, this.buildHeaders());
            log.info("[POST][strategy][URI={}] response: {}", uri, respStr);

            if (StringUtils.isEmpty(respStr)) {
                return strategyInfos;
            }

            JSONObject json = JSON.parseObject(respStr);
            if (json == null || json.size() == 0) {
                return strategyInfos;
            }
            String code = json.getString("code");
            if (code == null) {
                return strategyInfos;
            }

            if (!code.equals("0")) {
                // 如果因为验权问题，则重新获取权限信息；
                if (tokenErrorCodes.contains(code)) {
                    this.obtainStraAuth();
                }

                return strategyInfos;
            }

            strategyInfos = JSON.parseArray(json.getString("data"), StrategyInfo.class);
        } catch (Exception e) {
            log.error("请求策略服务异常", e);
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "请求策略系统异常", e);
        }

        return strategyInfos;
    }

    public StraAttrResponse queryStraAttrInfo(Integer type, String value) {
        String uri = this.strategyHost + QUERY_STRATEGY_ATTR_INFO_URL;
        Map<String, Object> params = new HashMap<>();
        params.put("attrType", type);
        params.put("attrValue", value);

        StraAttrResponse straAttr;
        try {
            log.info("[POST][strategy][URI={}] content: {}", uri, JSON.toJSONString(params));
            String respStr = HttpClientTemplate.doGet(uri, params, this.buildHeaders());
            log.info("[POST][strategy][URI={}] response: {}", uri, respStr);

            if (StringUtils.isEmpty(respStr)) {
                return null;
            }

            JSONObject json = JSON.parseObject(respStr);
            if (json == null || json.size() == 0) {
                return null;
            }
            String code = json.getString("code");
            if (code == null) {
                return null;
            }

            if (!code.equals("0")) {
                // 如果因为验权问题，则重新获取权限信息；
                if (tokenErrorCodes.contains(code)) {
                    this.obtainStraAuth();
                }

                return null;
            }

            straAttr = JSON.parseObject(json.getString("data"), StraAttrResponse.class);
        } catch (Exception e) {
            log.error("请求策略服务异常", e);
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "请求策略系统异常", e);
        }

        return straAttr;

    }

    /**
     * 请求策略服务，添加供商配置
     *
     * @param request
     * @return
     */
    public Boolean supplierConfig(StrategySupplierRequest request) {
        String uri = this.strategyHost + SUPPLIER_CONFIG_URL;
        String content = JSON.toJSONString(request);
        try {
            log.info("[POST][strategy][URI={}] content: {}", uri, content);
            String respStr = HttpClientTemplate.doPostBody(uri, content, this.buildHeaders());
            log.info("[POST][strategy][URI={}] response: {}", uri, respStr);

            if (StringUtils.isNotEmpty(respStr)) {
                JSONObject json = JSON.parseObject(respStr);
                if (json != null && json.size() > 0) {
                    String code = json.getString("code");
                    if (code.equals("0")) {
                        return Boolean.TRUE;
                    }
                }
            }
        } catch (Exception e) {
            log.error("请求策略服务异常", e);
        }

        return Boolean.FALSE;
    }

    /**
     * 请求策略服务的头信息
     *
     * @return
     */
    private Map<String, String> buildHeaders() {
        Map<String, String> headMap = new HashMap<>(8);
        // 验权信息
        headMap.put("Authorization", strategyToken);
        headMap.put("Content-type", "application/json");

        return headMap;
    }

    /**
     * 请求策略服务，初始化权限认证信息
     */
    private void obtainStraAuth() {
        Map<String, Object> param = new HashMap<>(4);
        param.put("userName", username);
        param.put("password", password);

        try {
            this.auth(param, authVersion.get());
        } catch (Exception e) {
            log.error("【策略服务】获取权限认证异常！", e);
        }
    }

    /**
     * 获取策略服务的权限认证
     *
     * @param authParam
     * @return
     */
    private synchronized void auth(Map<String, Object> authParam, long version) {
        log.info("【策略服务】获取权限认证，【开始】！！");
        if (authVersion.get() != version) {
            log.warn("【策略服务】获取权限认证，version失效！原version：{}，当前version：{}", version, authVersion.get());
            return;
        }

        String uri = this.strategyHost + STRATEGY_AUTH_URL;
        String content = JSON.toJSONString(authParam);
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        log.info("[POST][strategy][URI=" + uri + "]" + content);
        String respStr = HttpClientTemplate.doPost(uri, authParam, headers);
        log.info("[POST][strategy][URI=" + uri + "]" + respStr);

        if (StringUtils.isEmpty(respStr)) {
            throw new BusinessException(ExceptionStatus.E3001001.getCode(), "策略服务权限认证失败，策略服务返回为空");
        }

        JSONObject json = JSON.parseObject(respStr);
        Integer code = json.getInteger("code");
        if (code == null || code.intValue() != 0) {
            throw new BusinessException(ExceptionStatus.E3001001.getCode(), "策略服务权限认证失败，原因：" + json.getString("message"));
        }

        JSONObject data = json.getJSONObject("data");
        String token = data.getString("token");
        if (StringUtils.isEmpty(token)) {
            String message = json.getString("message");
            throw new BusinessException(ExceptionStatus.E3001001.getCode(), "策略服务权限认证失败，异常信息：" + message);
        }

        strategyToken = "ops-" + token;
        authVersion.getAndIncrement();
        log.info("【策略服务】权限认证，【成功】！！");
    }


    public static void main(String[] args) {
//        strategyToken = "ops-eyJhbGciOiJIUzUxMiJ9.eyJyYW5kb21LZXkiOiJvdzgweWQiLCJzdWIiOiJhZG1pbiIsImV4cCI6MTU0ODE0NjQyNywiaWF0IjoxNTQ3NTQxNjI3fQ.mqJ5ZPkO11Ncc7tNAXyJiu3wziGNxyCTDMX0xJpJo9YqAs-GK-q1AxaR067r5w_VBgQRMGcJ2ryXjoBbZK1sUA";
//        StrategyProxy strategyProxy = new StrategyProxy();
//        strategyProxy.strategyHost = "http://127.0.0.1:9098";
//        strategyProxy.tokenErrorCodes = new ArrayList<>();
//        strategyProxy.tokenErrorCodes.add("1002002");
//
//        StrategyRequest request = new StrategyRequest();
//        StrategyServiceHandler handler = new StrategyServiceHandler();
//        request.setChannelId(1);
//        request.setStraType(1);
////        request.setBizId("1");
//        List<StrategyAttr> attrs = handler.buildStraAttrValues("2000", "", "F0003");
//        StrategyAttr strategyAttr = new StrategyAttr();
//        strategyAttr.setType(3);
//        strategyAttr.setValue("u01");
//        attrs.add(strategyAttr);
//        request.setStraAttrValues(attrs);
//
//        List<StrategyInfo> strategyInfos = strategyProxy.queryStraInfo(request);
//        System.out.println(JSON.toJSONString(strategyInfos));
    }
}
